﻿/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Author:       François PIETTE @ Balteau-NDT
Creation:     Feb 11, 2015
Description:  Demo showing how to automate Balteau NDT control Balteau-NDT
              applications using a TCP/IP connection.
              This source is the class exposing methods to parse a parameter
              string (A semicolon separated list or key/value pairs).
Version:      1.00
Legal issues: This software is Open Source and subject to "The MIT License (MIT)"
              Copyright (C) 2015 Balteau-NDT
              Rue Voie de Liège 12, 4681 Hermalle Ss Argenteau, Belgium
              http://www.balteau-ndt.com
 
              Permission is hereby granted, free of charge, to any person 
              obtaining a copy of this software and associated documentation
              files (the "Software"), to deal in the Software without 
              restriction, including without limitation the rights to use, 
              copy, modify, merge, publish, distribute, sublicense, and/or 
              sell copies of the Software, and to permit persons to whom 
              the Software is furnished to do so, subject to the following 
              conditions:

              The above copyright notice and this permission notice shall 
              be included in all copies or substantial portions of the Software.

              THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
              EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
              OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
              NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
              HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
              WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
              OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
              DEALINGS IN THE SOFTWARE.

History:


 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Text;

namespace Balteau
{
    public static class ParamParsing
    {
        public static double MyStrToFloatDef(string aStrValue, double aDefValue)
        {
            double result;
            NumberStyles style = NumberStyles.AllowDecimalPoint;

            // We accepte either the local decimal separator or the English decimal separator.
            if (double.TryParse(aStrValue, style, CultureInfo.CurrentCulture, out result))
                return result;
            else {
                CultureInfo  culture = CultureInfo.CreateSpecificCulture("en-GB");
                if (CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator != culture.NumberFormat.NumberDecimalSeparator) {
                    if (double.TryParse(aStrValue, style, culture, out result))
                        return result;
                }
                return aDefValue;
            }
        }

        public static string MyFloatToStr(double value)
        {
            CultureInfo  culture = CultureInfo.CreateSpecificCulture("en-GB");
            return value.ToString("F", culture);
        }

        public static string MyFloatToStr(double value, int width, int prec, bool zeroPad)
        {
            CultureInfo  culture = CultureInfo.CreateSpecificCulture("en-GB");
            StringBuilder sb = new StringBuilder(value.ToString("F" + prec.ToString(), culture));
            if (zeroPad) {
                while (sb.Length < width)
                    sb.Insert(0, '0');
            }
            else {
                while (sb.Length < width)
                    sb.Insert(0, ' ');
            }
            return sb.ToString();
        }
        
        public static int ParamByNameAsInteger(string aParams, string aParamName, ref bool aStatus, int aDefValue)
        {
            string strValue = ParamByNameAsString(aParams, aParamName, ref aStatus, aDefValue.ToString());
            int result;
            if (aStatus && int.TryParse(strValue, out result))
                return result;
            else
                return aDefValue;
        }

        public static double ParamByNameAsFloat(string aParams, string aParamName, ref bool aStatus, double aDefValue)
        {
            string strValue = ParamByNameAsString(aParams, aParamName, ref aStatus, "");
            if (aStatus)
                return MyStrToFloatDef(strValue, aDefValue);
            else
                return aDefValue;
        }

        public static string ParamByNameAsString(string aParams, string aParamName, ref bool aStatus, string aDefValue)
        {
            int i, j;
            char ch;
            StringBuilder sb = new StringBuilder(); 

            aStatus = false;

            i = 0;
            while (i < aParams.Length) {
                j = i;
                while ((i < aParams.Length) && (aParams[i] != '='))
                    i++;
                if (i >= aParams.Length)
                    return aDefValue;
                if (string.Equals(aParamName, aParams.Substring(j, i - j), 
                                  StringComparison.OrdinalIgnoreCase)) {
                    // Found parameter name, extract value.
                    i++; // Skip '='
                    if ((i < aParams.Length) && (aParams[i] == '"')) {
                        // Value is between double quotes.
                        // Embedded double quotes and backslashes are prefixed
                        // by backslash.
                        aStatus = true;
                        i++; // Skip starting delimiter
                        while (i < aParams.Length) {
                            ch = aParams[i];
                            if (ch == '\\') {
                                i++;   // Skip escape character.
                                if (i >= aParams.Length)
                                    break;
                            }
                            else if (ch == '"')
                                break;
                            sb.Append(ch);
                        }
                    }
                    else {
                        // Value is up to semicolon or end of string.
                        j = i;
                        while ((i < aParams.Length) && (aParams[i] != ';'))
                            i++;
                        sb.Append(aParams.Substring(j, i - j));
                        aStatus = true;
                    }
                    return sb.ToString();
                }
                // Not good parameter name, skip to next.
                i++;  // Skip '='
                if ((i < aParams.Length) && (aParams[i] == '"')) {
                    i++;    // Skip starting delimiter.
                    while (i < aParams.Length) {
                        ch = aParams[i];
                        if (ch == '\\') {
                            i++;   // Skip escape character.
                            if (i >= aParams.Length)
                                break;
                        }
                        else if (ch == '"')
                            break;
                        i++;
                    }
                    i++; // Skip ending delimiter.
                }
                // Param ends with ';'.
                while ((i < aParams.Length) && (aParams[i] != ';'))
                    i++;
                i++;  // Skip semicolon.
            }
            return aDefValue;
        }
    }
}
